import numpy as np
import matplotlib.pyplot as plt


class BatteryEnergyStorageSystem:
    def __init__(self, Eb_cap, Td, SOCl, SOCu):
        self.Eb_cap = Eb_cap  # BESS 能量容量 (Wh)
        self.Td = Td  # 调度间隔时间 (min)
        self.SOCl = SOCl  # BESS 的 SOC 下限
        self.SOCu = SOCu  # BESS 的 SOC 上限
        self.SOC = 0.5  # 初始 SOC
        self.previous_status = None  # 上一个调度间隔的状态 (charge/discharge)
        self.P_d_history = []  # 记录调度功率历史
        self.SOC_history = []  # 记录 SOC 历史

    def online_power_dispatching(self, P_fl_current, P_fu_current, P_fl_next, P_fu_next):
        if self.previous_status is None:
            self.previous_status = 'charge'  # 初始化为充电状态

        # 当前调度间隔的功率初始值
        if self.previous_status == 'charge':
            P_d_i = P_fl_current
        else:
            P_d_i = P_fu_current

        # 获取前一个调度间隔的功率
        if len(self.P_d_history) > 0:
            P_d_i_minus_1 = self.P_d_history[-1]
        else:
            P_d_i_minus_1 = 0  # 初始功率

        # 计算当前 SOC
        def calculate_soc(P_d_i, P_d_i_minus_1):
            return self.SOC + (P_d_i_minus_1 - P_d_i) * (self.Td / 60) / self.Eb_cap

        SOC_current = calculate_soc(P_d_i, P_d_i_minus_1)
        SOC_next = calculate_soc(P_d_i, P_d_i)

        # 检查 SOC 是否在允许范围内
        status = None
        P_d_adjusted = P_d_i

        if self.previous_status == 'charge':
            # 检查当前 SOC 是否在允许范围内
            if self.SOCl <= SOC_current <= self.SOCu:
                # 检查下一个 SOC 是否在允许范围内
                if self.SOCl <= SOC_next <= self.SOCu:
                    status = 'charge'
                else:
                    P_d_adjusted = self.adjust_power_charge(P_fl_current, SOC_current, SOC_next)
                    status = 'charge'
            else:
                # 调整功率
                P_d_adjusted = self.adjust_power_charge(P_fl_current, SOC_current, SOC_next)
                status = 'charge'
        else:
            # 检查当前 SOC 是否在允许范围内
            if self.SOCl <= SOC_current <= self.SOCu:
                # 检查下一个 SOC 是否在允许范围内
                if self.SOCl <= SOC_next <= self.SOCu:
                    status = 'discharge'
                else:
                    P_d_adjusted = self.adjust_power_discharge(P_fu_current, SOC_current, SOC_next)
                    status = 'discharge'
            else:
                # 调整功率
                P_d_adjusted = self.adjust_power_discharge(P_fu_current, SOC_current, SOC_next)
                status = 'discharge'

        # 更新 SOC 和状态
        self.SOC = calculate_soc(P_d_adjusted, P_d_i_minus_1)
        self.previous_status = status

        # 记录调度功率和 SOC
        self.P_d_history.append(P_d_adjusted)
        self.SOC_history.append(self.SOC)

        return P_d_adjusted, status

    def adjust_power_charge(self, P_fl_current, SOC_current, SOC_next):
        # 简单的调整逻辑：如果 SOC 超出上限，降低功率至 P_fl_current * 0.5
        if SOC_next > self.SOCu:
            return P_fl_current * 0.5
        else:
            return P_fl_current

    def adjust_power_discharge(self, P_fu_current, SOC_current, SOC_next):
        # 简单的调整逻辑：如果 SOC 低于下限，提高功率至 P_fu_current * 1.5
        if SOC_next < self.SOCl:
            return P_fu_current * 1.5
        else:
            return P_fu_current


# 参数设置
T = 24 * 4  # 24 小时，每 15 分钟一个调度间隔
Eb_cap = 1000  # BESS 能量容量 (Wh)
Td = 15  # 调度间隔时间 (min)
SOCl = 0.1  # BESS 的 SOC 下限
SOCu = 0.9  # BESS 的 SOC 上限
confidence_interval = 0.03  # 预测置信区间

# 初始化 BESS
bess = BatteryEnergyStorageSystem(Eb_cap=Eb_cap, Td=Td, SOCl=SOCl, SOCu=SOCu)

# 生成功率预测序列
np.random.seed(0)
P_f = np.random.uniform(100, 500, T)  # 生成随机预测功率
P_fu = P_f * (1 + confidence_interval)  # 上边界预测功率
P_fl = P_f * (1 - confidence_interval)  # 下边界预测功率

# 初始化调度后的功率列表
P_d = []

for i in range(T):
    P_fl_current = P_fl[i]
    P_fu_current = P_fu[i]
    if i < T - 1:
        P_fl_next = P_fl[i + 1]
        P_fu_next = P_fu[i + 1]
    else:
        P_fl_next = P_fl[i]
        P_fu_next = P_fu[i]

    # 调用在线功率调度方法
    P_d_i, status = bess.online_power_dispatching(P_fl_current, P_fu_current, P_fl_next, P_fu_next)
    P_d.append(P_d_i)

# 绘制结果
time = np.arange(T)  # 时间轴 (调度间隔)

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))

# 绘制调度功率与预测功率
ax1.plot(time, P_d, label='Dispatched Power', color='orange', linewidth=2)
ax1.plot(time, P_f, label='Predicted Power', color='blue', linestyle='--')
ax1.fill_between(time, P_fu, P_fl, color='gray', alpha=0.3, label='Confidence Interval')
ax1.set_title('Power Dispatching and Prediction')
ax1.set_xlabel('Time (15 min intervals)')
ax1.set_ylabel('Power (W)')
ax1.legend()

# 绘制 SOC
ax2.plot(time, bess.SOC_history, label='SOC', color='green')
ax2.axhline(y=SOCl, color='red', linestyle='--', label='SOC Lower Limit')
ax2.axhline(y=SOCu, color='blue', linestyle='--', label='SOC Upper Limit')
ax2.set_title('State of Charge (SOC) of BESS')
ax2.set_xlabel('Time (15 min intervals)')
ax2.set_ylabel('SOC')
ax2.legend()

plt.tight_layout()
plt.show()